﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud

#if NO_SILVERLIGHT

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
    public static class Serialization
    {
        #region Methods

        public static object DeserializeFromBinary(this MemoryStream ms)
        {
            return GetFormatter().Deserialize(ms);
        }

        public static object DeserializeFromBinary(this MemoryStream ms, IFormatter bf)
        {
            return bf.Deserialize(ms);
        }

        public static object DeserializeFromBinary(this FileStream ms)
        {
            return GetFormatter().Deserialize(ms);
        }

        //public static byte[] SerializeToZippedBinary(object o)
        //{
        //    byte[] bytes;
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        GetFormatter().Serialize(ms, o);
        //        bytes = ms.ToArray();
        //    }
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        Stream stream = new DeflaterOutputStream(ms,
        //        new Deflater(Deflater.BEST_COMPRESSION), bytes.Length);
        //        try
        //        {
        //            stream.Write(bytes, 0, bytes.Length);
        //        }
        //        finally
        //        {
        //            stream.Close();
        //            stream.Dispose();
        //        }
        //        return ms.ToArray();
        //    }
        //}
        //public static object DeserializeFromZippedBinary(this byte[] byteData)
        //{
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        byte[] data = new byte[32000];
        //        Stream s = new InflaterInputStream(new MemoryStream(byteData));
        //        try
        //        {
        //            while (true)
        //            {
        //                int bytes = s.Read(data, 0, 32000);
        //                if (bytes < 1) break;
        //                ms.Write(data, 0, bytes);
        //            }
        //        }
        //        finally
        //        {
        //            s.Close();
        //            s.Dispose();
        //        }
        //        return ms.DeserializeFromBinary();
        //    }
        //}
        public static object DeserializeFromCompressedBinary(this MemoryStream ms)
        {
            using (MemoryStream m = new MemoryStream(ms.GetBuffer().Decompress()))
            {
                m.Seek(0, SeekOrigin.Begin);
                return m.DeserializeFromBinary();
            }
        }

        //public static byte[] SerializeToCompressedBinary(this object o)
        //{
        //    byte[] data;
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        try
        //        {
        //            Stopwatch watch = new Stopwatch();
        //            watch.Start();
        //            GetFormatter().Serialize(ms, o);
        //            watch.Stop();
        //            Console.WriteLine(watch.ElapsedMilliseconds);
        //        }
        //        catch { throw; }
        //        data = ms.ToArray();
        //    }
        //    return data.Compress();
        //}
        public static object DeserializeFromCompressedBinary(this byte[] data)
        {
            object o = null;
            byte[] decompressed = data.Decompress();
            using (MemoryStream ms = new MemoryStream(decompressed))
            {
                ms.Seek(0, SeekOrigin.Begin);
                try
                {
                    o = ms.DeserializeFromBinary();
                }
                catch {  o = null; }
                ms.Close();
            }
            return o;
        }

        public static object DeserializeFromBinary(this byte[] data)
        {
            object o = null;            
            using (MemoryStream ms = new MemoryStream(data))
            {
                ms.Seek(0, SeekOrigin.Begin);
                try
                {
                    o = ms.DeserializeFromBinary();
                }
                catch { o = null; }
                ms.Close();
            }
            return o;
        }

        public static object DeserializeFromCompressedBinary(this FileStream fs)
        {
            byte[] data;
            long len = fs.Length;

            using (BinaryReader br = new BinaryReader(fs))
            {
                data = br.ReadBytes(Convert.ToInt32(len));
            }

            return data.DeserializeFromCompressedBinary();
        }

        public static List<T> ReadStorage<T>(this string dir)
            where T : class
        {
            List<T> results = new List<T>();
            string file = typeof(T).Name;

            //if (File.Exists(file))
            //{
            //    using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            //    {
            //        Stopwatch sw = new Stopwatch();
            //        sw.Start();
            //        try
            //        {
            //            object o = fs.DeserializeFromCompressedBinary();
            //            sw.Stop();
            //            Console.WriteLine(sw.ElapsedMilliseconds);

            //            return new List<T>((T[])o);
            //        }
            //        catch { throw; }
            //    }
            //}

            return results;
        }

        public static void SaveStorage<T>(this string dir, List<T> results)
            where T : class
        {
            PropertyDescriptor prop = typeof(T).IDProperty();
            string file = typeof(T).Name;

            T[] arrayResults = results.ToArray();
            byte[] bytes = arrayResults.SerializeToCompressedBinary();
            using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.ReadWrite))
            {
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    bw.Write(bytes);
                    bw.Close();
                }
                fs.Close();
            }
        }

        public static byte[] SerializeToBinary(this object o)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                GetFormatter().Serialize(ms, o);
                return ms.ToArray();
            }
        }

        public static void SerializeToBinaryMemoryStream(this object o, MemoryStream ms)
        {
            GetFormatter().Serialize(ms, o);
        }

        public static byte[] SerializeToCompressedBinary(this object o)
        {
            byte[] data;
            using (MemoryStream ms = new MemoryStream())
            {
                try
                {
                    GetFormatter().Serialize(ms, o);
                }
                catch { throw; }
                data = ms.ToArray();
                return data.Compress();
            }            
        }

        public static void SerializeToCompressedBinaryMemoryStream(this object o, MemoryStream ms)
        {
            byte[] data = o.SerializeToCompressedBinary();
            ms.Write(data, 0, data.Length);
        }

        private static IFormatter GetFormatter()
        {
            //return new NxBinaryFormatter();
            return new BinaryFormatter();
        }

        #endregion Methods
    }
}

#else

#endif